package com.gk.study.interceptor;

import com.gk.study.utils.ThreadLocalUtil;
import com.google.gson.Gson;
import com.gk.study.common.APIResponse;
import com.gk.study.entity.OpLog;
import com.gk.study.service.OpLogService;
import com.gk.study.service.UserService;
import com.gk.study.utils.IpUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 该拦截器有两个用途：1.拦截request记录log 2.接口验权
 */
@Component
public class AccessInterceptor extends HandlerInterceptorAdapter {

    private Logger logger = LoggerFactory.getLogger(AccessInterceptor.class);

    private static OpLogService service;

    private static UserService userService;

    @Autowired
    public void setOpLogService(OpLogService service) {
        // 为解决先@Component 后@Autowired失效的方案
        AccessInterceptor.service = service;
    }

    @Autowired
    public void setUserService(UserService userService) {
        // 为解决先@Component 后@Autowired失效的方案
        AccessInterceptor.userService = userService;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 记录请求开始时间
        request.setAttribute("_startTime", System.currentTimeMillis());
        //**********************验权代码*************************
        // 判断是否为处理请求的方法，如果不是则直接返回true（不进行权限验证）
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // 将handler转换为HandlerMethod对象，以便获取方法信息
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 获取处理方法
        Method method = handlerMethod.getMethod();
        // 在这里可以进行权限验证，例如检查用户是否有访问该方法的权限，如果没有权限则返回false
        // 这里暂时省略权限验证逻辑，直接返回true
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理完成后执行的操作，这里暂时不需要实现任何操作
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //**********************记录log代码*************************
        // 计算请求处理耗时
        Long endTime = System.currentTimeMillis();
        Long startTime = (Long) request.getAttribute("_startTime");
        Long diff = (endTime - startTime);
        // 创建日志对象并设置相关属性
        OpLog opLog = new OpLog();
        opLog.setUsername(ThreadLocalUtil.get()); // 记录当前用户名
        opLog.setReIp(IpUtils.getIpAddr(request)); // 获取请求IP地址
        opLog.setReMethod(request.getMethod()); // 获取请求方法（GET、POST等）
        opLog.setReUrl(request.getRequestURI()); // 获取请求URL
        opLog.setReUa(request.getHeader(HttpHeaders.USER_AGENT)); // 获取请求头中的User-Agent字段
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        opLog.setReTime(formatter.format(new Date())); // 记录请求时间
        opLog.setAccessTime(String.valueOf(diff)); // 记录请求处理耗时
        // 调用OpLogService的createOpLog方法保存日志信息
        service.createOpLog(opLog);
    }

    public void writeResponse(HttpServletResponse response, APIResponse apiResponse) throws IOException {
        // 设置响应状态码为200，表示请求成功
        response.setStatus(200);
        // 允许跨域访问
        response.setHeader("Access-Control-Allow-Origin", "*");
        // 禁用缓存
        response.setHeader("Cache-Control", "no-cache");
        // 设置字符编码为UTF-8
        response.setCharacterEncoding("UTF-8");
        // 设置响应内容类型为application/json
        response.setContentType("application/json");
        // 使用Gson将APIResponse对象转换为JSON字符串
        Gson gson = new Gson();
        String jsonStr = gson.toJson(apiResponse);
        // 将JSON字符串写入响应输出流
        response.getWriter().println(jsonStr);
        // 刷新输出流，确保数据被发送到客户端
        response.getWriter().flush();
    }
}
